﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace theguineasyndrome
{
    public class Animation
    {
        // texture
        private Texture2D sprite;

        // time
        private int elapsedTime;
        private int frameTime;

        // frame
        private int currentFrame;
        private int frameLine;
        private int frameCount;
        private bool loop;
        private Vector2 frameSize;
        private Vector2 origin;
        private float rotation;
        private Rectangle srcRect;
        private Rectangle rectangle;
        private Vector2 position;
        private Color color;
        private float scale;
        private bool flipX;
        private bool flipY;

        private bool absolute;

        // dimensions
        public float Width
        {
            get { return frameSize.X; }
        }

        public float Height
        {
            get { return frameSize.Y; }
        }

        public float X
        {
            get { return position.X; }
        }

        public float Y
        {
            get { return position.Y; }
        }

        public Vector2 Position
        {
            get { return position; }
        }

        public bool xFliped
        {
            get { return flipX; }
        }

        public bool yFliped
        {
            get { return flipY; }
        }

        public int CurrentFrame
        {
            get { return currentFrame; }
        }

        // active
        private bool active;

        public Animation(Texture2D sprite, Vector2 frameSize, int frameTime, bool loop)
        {
            this.sprite = sprite;
            this.frameSize = frameSize;
            this.frameTime = frameTime;
            this.loop = loop;

            frameCount = sprite.Width / (int)frameSize.X;
            frameLine = 0;
            currentFrame = 0;
            active = true;

            origin = new Vector2();
            rotation = 0;
            scale = 1;
            position = new Vector2();

            srcRect = new Rectangle(0, 0, (int)frameSize.X, (int)frameSize.Y);
            rectangle = new Rectangle(0, 0, (int)frameSize.X, (int)frameSize.Y);

            color = Color.White;

            absolute = false;
        }

        public void setAbsolute(bool absolute)
        {
            this.absolute = absolute;
        }

        public void setOrigin(Vector2 origin)
        {
            this.origin = origin;
        }

        public void setRotation(float rotation)
        {
            this.rotation = rotation;
        }

        public void setColor(Color color)
        {
            this.color = color;
        }

        public void setScale(float scale)
        {
            this.scale = scale;
        }

        public float getScale()
        {
            return scale;
        }

        public void flip(bool x, bool y)
        {
            flipX = x;
            flipY = y;
        }

        public Animation copy()
        {
            return new Animation(sprite, frameSize, frameTime, loop);
        }

        public void copyState(Animation animation)
        {
            frameLine = animation.frameLine;
            currentFrame = animation.currentFrame;
            flipX = animation.flipX;
            flipY = animation.flipY;
            position.X = animation.position.X;
            position.Y = animation.position.Y;
            rectangle.X = animation.rectangle.X;
            rectangle.Y = animation.rectangle.Y;

            srcRect.X = currentFrame * (int)frameSize.X;
            srcRect.Y = frameLine * (int)frameSize.Y;
            srcRect.Width = (int)frameSize.X;
            srcRect.Height = (int)frameSize.Y;
        }

        public void setPosition(Vector2 position)
        {
            rectangle.X = (int)position.X;
            rectangle.Y = (int)position.Y;
            this.position = position;
        }

        public void setFrameLine(int frameLine)
        {
            this.frameLine = frameLine;
            currentFrame = 0;

            srcRect.X = currentFrame * (int)frameSize.X;
            srcRect.Y = frameLine * (int)frameSize.Y;
        }

        public void resetDimensions()
        {
            srcRect.X = currentFrame * (int)frameSize.X;
            srcRect.Y = frameLine * (int)frameSize.Y;
            srcRect.Width = (int)Width;
            srcRect.Height = (int)Height;

            rectangle.X = (int)position.X;
            rectangle.Y = (int)position.Y;
            rectangle.Width = (int)Width;
            rectangle.Height = (int)Height;
        }

        public void setHeightFromTop(int height)
        {
            rectangle.Height = height;
            srcRect.Height = height;
        }

        public void setHeightFromBottom(int height)
        {
            rectangle.Y = (int)(rectangle.Y + Height - height);
            rectangle.Height = height;
            srcRect.Y = (int)(srcRect.Y + Height - height);
            srcRect.Height = height;
        }

        public void setWidthFromLeft(int width)
        {
            rectangle.Width = width;

            if (flipX)
                srcRect.X = (int)(srcRect.X + Width - width);

            srcRect.Width = width;
        }

        public void setWidthFromRight(int width)
        {
            rectangle.X = (int)(rectangle.X + Width - width);
            rectangle.Width = width;

            if (!flipX)
                srcRect.X = (int)(srcRect.X + Width - width);

            srcRect.Width = width;
        }

        public void Update(GameTime gameTime)
        {
            elapsedTime += (int)gameTime.ElapsedGameTime.TotalMilliseconds;
            if (elapsedTime > frameTime)
            {
                currentFrame++;
                if (currentFrame == frameCount)
                {
                    currentFrame = 0;
                    if (!loop)
                        active = false;
                }
                srcRect.X = currentFrame * (int)frameSize.X;
                srcRect.Y = frameLine * (int)frameSize.Y;
                srcRect.Width = (int)frameSize.X;
                srcRect.Height = (int)frameSize.Y;
                elapsedTime = 0;
            }
        }

        public void Draw(SpriteBatch spriteBatch, Camera camera)
        {
            if (active)
            {
                SpriteEffects effects = SpriteEffects.None;

                if (flipX)
                    effects |= SpriteEffects.FlipHorizontally;

                else if (flipY)
                    effects |= SpriteEffects.FlipVertically;

                if (absolute || camera == null)
                {
                    if (scale == 1) // better rendering
                        spriteBatch.Draw(sprite, rectangle, srcRect, color, rotation, origin, effects, 0);

                    else
                        spriteBatch.Draw(sprite, position, srcRect, color, rotation, origin, scale, effects, 0);
                }
                else
                {
                    if (scale == 1) // better rendering
                        spriteBatch.Draw(sprite, camera.getDstRect(rectangle), srcRect, color, rotation, origin, effects, 0);

                    else
                        spriteBatch.Draw(sprite, camera.getDstPoint(position), srcRect, color, rotation, origin, scale, effects, 0);
                }
            }
        }
    }
}
